using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace CodeStory.SmartUpload
{
	public class SmartBuffer
	{
		byte[] innerbuffer;
		int dataLength = 0;
		object syncRoot;

		public object SyncRoot {
			get {
				if (this.syncRoot == null) {
					Interlocked.CompareExchange(ref this.syncRoot,new object(),null);
				}
				return syncRoot; }
		}

		public int DataLength {
			get { return dataLength; }
		}
		public SmartBuffer():this(0x20000) {

		}
		public SmartBuffer(int capacity) {
			innerbuffer = new byte[capacity];
		}

		public void Append(byte[] buffer,int offset,int lenght) {
			EnsureBufferSize(DataLength + lenght);
			Array.Copy(buffer, offset, innerbuffer, DataLength, lenght);
			this.dataLength += lenght;
		}
		public byte this[int index] {
			get {
				if (index < 0)
					throw new IndexOutOfRangeException();
				while (index >= DataLength) {
					Thread.Sleep(200);
				}
				return innerbuffer[index];
			}
		}

		public bool Equals(int start,int lenght,byte[] data) {
			if (data == null) {
				throw new ArgumentNullException();
			}
			if (data.Length != lenght) {
				throw new ArgumentException("","data");
			}
			if (start + lenght > DataLength) {
				throw new ArgumentOutOfRangeException();
			}
			if (start < 0) return false;
			for (int i = 0; i < lenght; i++) {
				if (innerbuffer[start + i] != data[i]) return false;
			}
			return true;
		}

		public byte[] GetAllBytes() {
			return GetBytes(0,DataLength);
		}

		public byte[] GetBytes(int offset, int lenght) {
			byte[] result = new byte[lenght];
			Array.Copy(innerbuffer, offset, result, 0, lenght);
			return result;
		}

		public byte[] Remove(int startIndex, int length) {
			byte[] result = new byte[length];
			Array.Copy(innerbuffer, startIndex, result, 0, length);
			Array.Copy(innerbuffer, startIndex + length, innerbuffer, startIndex, DataLength - startIndex - length);
			dataLength -= length;
			return result;
		}

		private void EnsureBufferSize(int size) {
			int s = innerbuffer.Length;
			if (s > size) return;
			while (s < size) {
				s *= 2;
			}
			byte[] temp = new byte[s];
			Array.Copy(innerbuffer, 0, temp, 0, DataLength);
			innerbuffer = temp;
		}
	}
}
